GLU

Gated Linear Unit(门控线性单元)算子。该算子将输入张量在指定维度(split_dim)上分割成两个相等的部分(A和B),然后对第二部分(B)应用Sigmoid激活函数,并将其与第一部分(A)逐元素相乘。

\[\text{out} = A \otimes \sigma(B)\]

其中,A和B是输入张量沿 split_dim 维度分割后的两个子张量,\(\sigma\) 是Sigmoid函数,\(\otimes\) 表示逐元素乘法。

输入:
  • in_data - 输入张量的数据地址。

  • params - 参数打包数组,格式如下:
    • split_data - 一个指针数组,用于存放分割后的子张量地址(作为临时缓冲区)。

    • ndim - 输入张量的维度数量。

    • split_dim - 执行分割操作的目标维度轴。

    • input_shape - 指向一个整数数组的指针,该数组描述了输入张量的形状。

    • num_split - 分割的数量,对于GLU操作,此值应为2。

    • split_sizes - 指向一个整数数组的指针,该数组描述了每个子张量在 split_dim 维度上的大小。

    • strides - 指向一个整数数组的指针,用于存放为张量索引预先计算好的步长。

    • len - 输出张量中的元素总数。

  • core_mask - 核掩码 (仅共享存储版本需要)。

输出:
  • out_data - 存储GLU计算结果的张量。其形状与输入张量相同,但在 split_dim 维度上的大小减半。

支持平台:

FT78NE MT7004

备注

  • FT78NE支持fp32和int8类型。

  • MT7004支持fp16和fp32类型。

共享存储版本:

void i8_glu_s(int8_t *in_data, int8_t *out_data, long long *params, int core_mask)
void hp_glu_s(half *in_data, half *out_data, long long *params, int core_mask)
void fp_glu_s(float *in_data, float *out_data, long long *params, int core_mask)

C调用示例:

 1// 7004平台, fp32示例
 2#include <stdio.h>
 3#include "glu.h"
 4
 5int main(int argc, char* argv[]) {
 6    float *in_data = (float *)0xA0000000;      // input在DDR空间
 7    float *out_data = (float *)0xC0000000;     // output在DDR空间
 8    float *split_data_buf[2];                  // 临时缓冲区指针
 9    // ... (需要为split_data_buf分配内存)
10
11    // 假设张量属性已定义
12    int ndim = 2;
13    int split_dim = 1;
14    int input_shape[] = {2, 4};
15    int num_split = 2;
16    int split_sizes[] = {2, 2};
17    int len = 4;
18    int strides[2]; // 需要预先计算
19    int core_mask = 0xff;
20
21    long long params[8];
22    params[0] = (long long)split_data_buf;
23    params[1] = (long long)ndim;
24    params[2] = (long long)split_dim;
25    params[3] = (long long)input_shape;
26    params[4] = (long long)num_split;
27    params[5] = (long long)split_sizes;
28    params[6] = (long long)strides;
29    params[7] = (long long)len;
30
31    fp_glu_s(in_data, out_data, params, core_mask);
32    return 0;
33}

私有存储版本:

void i8_glu_p(int8_t *in_data, int8_t *out_data, long long *params)
void hp_glu_p(half *in_data, half *out_data, long long *params)
void fp_glu_p(float *in_data, float *out_data, long long *params)

C调用示例:

 1// 7004平台, fp32示例
 2#include <stdio.h>
 3#include "glu.h"
 4
 5int main(int argc, char* argv[]) {
 6    float *in_data = (float *)0x10000000;     // input在L2空间
 7    float *out_data = (float *)0x10001000;    // output在L2空间
 8    float *split_data_buf[2];                 // 临时缓冲区指针
 9    // ... (需要为split_data_buf分配内存)
10
11    // 假设张量属性已定义
12    int ndim = 2;
13    int split_dim = 1;
14    int input_shape[] = {2, 4};
15    int num_split = 2;
16    int split_sizes[] = {2, 2};
17    int len = 4;
18    int strides[2]; // 需要预先计算
19
20    long long params[8];
21    params[0] = (long long)split_data_buf;
22    params[1] = (long long)ndim;
23    params[2] = (long long)split_dim;
24    params[3] = (long long)input_shape;
25    params[4] = (long long)num_split;
26    params[5] = (long long)split_sizes;
27    params[6] = (long long)strides;
28    params[7] = (long long)len;
29
30    fp_glu_p(in_data, params);
31    return 0;
32}